<script setup lang="ts">
import YkPagination from '@yk/components/pagination/YkPagination.vue'
import { Pages } from '@typings/pages'
import { Download, Plus } from '@element-plus/icons-vue'
import YkTableColumn from '@yk/components/table-column/YkTableColumn.vue'
import { ObjectUtil } from '@utils/object-util'
import { ElForm, ElTable, UploadUserFile } from 'element-plus'
import YkUploadFile from '@yk/components/upload/upload-file/YkUploadFile.vue'
import YkUploadImage from '@yk/components/upload/upload-image/YkUploadImage.vue'
import { gatewayDefaultImageMap, gatewayModelMap, gatewayModelToTypeMap } from '@/dataset'
import { GatewayDTO, GatewaySaveForm } from '@/api/entity/gateway'
import { ElValidator, phoneRule, positionRule, required } from '@utils/form-rule'
import YkCoordinatePickup from '@yk/components/coordinate-pickup/YkCoordinatePickup.vue'
import {
  addGatewayAPI,
  delGatewayAPI,
  editGatewayAPI, getGatewayTypeByNumberAPI,
  getGatewayListByPageAPI,
  getGatewayPageNumByIdAPI, gatewayTransferAPI
} from '@/api/gateway'
import settings from '@/settings'
import { FileUtil, MountedCheck } from '@/utils'
import { useDeviceStatusStore } from '@/dataset/device-status/store'
import { TableUtil } from '@utils/table-util'
import { importFileAPI } from '@/api/file'
import { ServerEnum } from '@/api/enum/server'
import DebuggerGateway from '@views/gateway/components/debugger-gateway/DebuggerGateway.vue'
import { getEncryptVStr } from '@/router/interceptor/security'
import { getToken } from '@utils/authorization/token'

defineOptions({ name: 'GatewayManage' })
const router = useRouter()
const route = useRoute()

/**
 * 支持params参数
 * @param id 【非必填】-聚焦到表格的一行
 */
const mc = new MountedCheck()
onMounted(async () => {
  await initFocusTableRow()
  getTableData()
  deviceStatusStore.startUpdateStatus()
  mc.end()
})

onActivated(() => {
  if (mc.isMounted()) return
  getTableData()
  deviceStatusStore.startUpdateStatus()
})

onDeactivated(() => {
  deviceStatusStore.stopUpdateStatus()
})

onBeforeUnmount(() => {
  deviceStatusStore.stopUpdateStatus()
})

// region TODO 查询
const searchParams = reactive({
  q: '',
  status: null
})
function searchHandle () {
  pages.pageNum = 1
  exportParams.value = ObjectUtil.copy(searchParams)
  getTableData()
}
// endregion

// region TODO 表格数据
const pages = reactive(new Pages())
const tableDataRef = shallowRef<InstanceType<typeof ElTable>>()
const tableData = shallowRef<GatewayDTO[]>([])
function getTableData () {
  const loading = ElLoading.service()
  getGatewayListByPageAPI({
    ...pages.getParams(),
    param: searchParams
  }).then((res) => {
    res.result().then((rdata) => {
      tableData.value = rdata.records || []
      pages.total = rdata.total
      focusTableRow()
    })
  }).finally(loading.close)
}
function delTableItem (id: string) {
  ElMessageBox.confirm('删除当前网关？', '删除提醒').then(() => {
    delGatewayAPI({ id }).then((res) => {
      res.result().then(() => {
        getTableData()
      })
    })
  })
}
// endregion

// region TODO 聚焦某一行
let focusTableRowKey = ''
async function initFocusTableRow () {
  return new Promise((resolve) => {
    focusTableRowKey = (route.params.id as string)
    if (focusTableRowKey) {
      getGatewayPageNumByIdAPI({
        param: { id: focusTableRowKey },
        ...pages.getParams()
      }).then((res) => {
        res.result().then((rdata) => {
          pages.pageNum = rdata.data || 1
          resolve(undefined)
        }).finally(() => resolve(undefined))
      }).catch(() => resolve(undefined))
    } else {
      resolve(undefined)
    }
  })
}
// 聚焦行
function focusTableRow () {
  if (focusTableRowKey) {
    nextTick(() => {
      TableUtil.highlightRow(tableDataRef.value, tableData.value.findIndex(item => item.id === focusTableRowKey))
      focusTableRowKey = ''
    })
  }
}
// endregion

// region TODO 在线状态
const deviceStatusStore = useDeviceStatusStore()
// endregion

// region TODO 导出
const exportParams = shallowRef<typeof searchParams>()
// endregion

// region TODO 导入
const uploadFile = shallowRef<UploadUserFile>()
const importDialogModel = shallowRef(false)
const importErrorTableData = shallowRef<{
  rowIndex: number, errorMsg: string
}[]>([])
function loadTableData (e: UploadUserFile) {
  uploadFile.value = null
  const loading = ElLoading.service()
  importFileAPI(ServerEnum.System + '/gateWay/importExcel', e.raw).then((res) => {
    res.result().then((rdata) => {
      const data = rdata.data.list || []
      if (data.length) {
        importErrorTableData.value = data.map(item => ({ rowIndex: item.rowIndex, errorMsg: item.errorMsg }))
        importDialogModel.value = true
      } else {
        ElMessage.success('已导入')
      }
    })
  }).finally(loading.close)
}
// endregion

// region TODO 添加/修改表单
const saveForm = ref(new GatewaySaveForm())
const saveFormRules = {
  // 网关名称
  name: [required('网关名称为必填项')],
  // 网关编号
  number: [required('网关编号为必填项'), {
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      getGatewayTypeByNumberAPI({ number: value }).then((res) => {
        res.result().then((rdata) => {
          saveForm.value.model = rdata.data
          callback(undefined)
        }).catch((rdata) => {
          callback(Error(rdata.msg))
        })
      })
    },
    trigger: 'blur'
  } as ElValidator],
  // 通讯密码
  // communicationPassword: [required('通讯密码为必填项')],
  // 经纬度
  latitudeLongitude: [positionRule],
  // 主题
  topic: [required('网关主题为必填项'), {
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      callback(/.*\/data/.test(value) ? undefined : Error('主题必须以/data结尾'))
    },
    trigger: 'blur'
  } as ElValidator]
}
const saveFormRef = shallowRef<InstanceType<typeof ElForm>>()
const gatewayImageFile = shallowRef<UploadUserFile>(null)

// region TODO 对话框
const saveFormDialogModel = ref(false)
function showSaveFormDialog (item?: GatewayDTO) {
  saveFormDialogModel.value = true
  if (item) {
    nextTick(() => {
      ObjectUtil.updateVal(saveForm.value, item)
      if (saveForm.value.url) {
        gatewayImageFile.value = { name: '', status: 'success', url: settings.URL.IMAGE_PREFIX + saveForm.value.url }
      }
    })
  }
}
function closeSaveFormDialog () {
  saveFormRef.value.resetFields()
  saveForm.value.id = null
  gatewayImageFile.value = null
  saveFormDialogModel.value = false
}
function submitSaveForm () {
  saveFormRef.value.validate().then(async () => {
    const loading = ElLoading.service()
    if (gatewayImageFile.value?.raw) {
      loading.setText('正在上传图片...')
      const url = await FileUtil.updateFile(gatewayImageFile.value.raw)
      if (url) saveForm.value.url = url
      else {
        loading.close()
        return
      }
    } else if (!gatewayImageFile.value) {
      saveForm.value.url = ''
    }
    loading.setText('正在保存...')
    const params = ObjectUtil.copy(saveForm.value)
    const result = saveForm.value.id ? editGatewayAPI(params) : addGatewayAPI(params)
    result.then((res) => {
      res.result().then(() => {
        ElMessage.success('保存成功')
        closeSaveFormDialog()
        getTableData()
      })
    }).finally(loading.close)
  })
  // MessageBoxResult.confirm('网关添加成功，前往查看网关参数', '添加成功', {
  //   confirmButtonText: '调试窗口',
  //   cancelButtonText: '关闭',
  //   type: 'success'
  // })
}
// endregion
// endregion

// region TODO 坐标拾取
const coordinatePickupDialogModel = ref(false)
function showCoordinatePickupDialog () {
  coordinatePickupDialogModel.value = true
}
// endregion

// region TODO 调试
const debuggerDialogModel = ref(false)
const debuggerGatewayInfo = shallowRef<GatewayDTO>()
function showDebuggerDialog (item: GatewayDTO) {
  debuggerGatewayInfo.value = item
  debuggerDialogModel.value = true
}
function closeDebuggerDialog () {
  debuggerDialogModel.value = false
}
// endregion

// region TODO 网关转让
const gatewayTransferDialogModel = ref(false)
const gatewayTransferForm = ref({
  // 网关id
  id: '',
  // 网关名称
  name: '',
  // 分享人手机号
  phone: ''
})
const gatewayTransferFormRules = shallowRef({
  phone: [required('分享人手机号为必填项'), phoneRule]
})
const gatewayTransferFormRef = shallowRef<InstanceType<typeof ElForm>>()

function showGatewayTransferDialog (item: GatewayDTO) {
  ElMessageBox.confirm('网关转让会将当前网关以及关联的设备等数据一并转让，您将不再拥有该网关以及其关联的设备，是否继续？', '警告提醒', { type: 'warning' }).then(() => {
    gatewayTransferDialogModel.value = true
    nextTick(() => {
      gatewayTransferForm.value.id = item.id
      gatewayTransferForm.value.name = item.name
    })
  })
}
function closeGatewayTransferDialog () {
  gatewayTransferDialogModel.value = false
  gatewayTransferFormRef.value.resetFields()
}
function gatewayTransferFormSubmit () {
  gatewayTransferFormRef.value.validate().then(() => {
    ElMessageBox.confirm('请再次确认转让操作，您将不再拥有该网关以及其关联的设备，是否继续？', '确认操作').then(() => {
      const loading = ElLoading.service()
      gatewayTransferAPI(gatewayTransferForm.value).then((res) => {
        res.result().then(() => {
          ElMessage.success('网关已转让')
          closeGatewayTransferDialog()
          getTableData()
        })
      }).finally(loading.close)
    })
  })
}
// endregion

// region TODO 跳转
function toDeviceData (id: string) {
  router.push({ name: 'DeviceData', query: { id } })
}
// endregion

</script>

<template>
  <div class="layout_view d-flex" style="min-height: 100%">
    <div class="c_card-page w-100">
      <div class="c_card_header c_card-title bor-divider-b">网关管理</div>
      <!--搜索表单-->
      <el-form inline class="c_form-search pt-16" @submit.prevent="searchHandle">
        <el-form-item label="网关名称">
          <el-input v-model="searchParams.q" placeholder="网关名称/编号搜索" />
        </el-form-item>
        <el-form-item>
          <el-select v-model="searchParams.status" placeholder="全部状态" clearable>
            <el-option :value="null">全部</el-option>
            <el-option label="在线" :value="true" />
            <el-option label="离线" :value="false" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="searchHandle">查询</el-button>
        </el-form-item>
      </el-form>
      <div />
      <!--功能栏-->
      <div class="d-flex-between">
        <div class="d-flex">
          <el-button type="primary" :icon="Plus as any" @click="showSaveFormDialog()">添加网关</el-button>
          <yk-upload-file v-model="uploadFile" class="ml-12" is-none @change="loadTableData">
            <el-button type="success">批量导入</el-button>
          </yk-upload-file>
          <export-file url="/gateWay/exportTemplate">
            <el-button type="success" class="ml-12" plain>下载模板</el-button>
          </export-file>
        </div>
        <export-file url="/gateWay/export" :params="exportParams">
          <el-button class="c_btn--export" :icon="Download as any">导出</el-button>
        </export-file>
      </div>
      <!--表格-->
      <el-table ref="tableDataRef" class="mt-16 c_table-page w-100" stripe :data="tableData">
        <el-table-column label="#" type="expand">
          <template #default="scope">
            <div v-if="scope.row.deviceDTOList.length" class="table__device-list px-20 py-16 d-grid text-color-primary fs-14">
              <span v-for="(item, index) in scope.row.deviceDTOList" :key="item">设备{{ index + 1 }}：
                <el-link type="primary" @click="toDeviceData(item.id)">{{ item.deviceName }}</el-link>
              </span>
            </div>
            <div v-else class="text-center w-100 text-color-placeholder">暂无关联设备</div>
          </template>
        </el-table-column>
        <el-table-column label="状态" prop="">
          <template #default="scope">
            <el-tag v-if="deviceStatusStore.gatewaysStatus[scope.row.id]" type="success" effect="dark" size="small">在线</el-tag>
            <el-tag v-else type="info" effect="dark" size="small">离线</el-tag>
          </template>
        </el-table-column>
        <yk-table-column label="网关名称" prop="name" />
        <yk-table-column label="网关编号" prop="number" />
        <yk-table-column label="网关型号" prop="model" />
        <yk-table-column label="版本" prop="version" />
        <yk-table-column label="物联网卡号" prop="cardNumber">
          <!--<template #default="scope">-->
          <!--  <el-link type="primary">{{ scope.row.cardNumber }}</el-link>-->
          <!--</template>-->
        </yk-table-column>
        <yk-table-column label="GPS" prop="latitudeLongitude" />
        <el-table-column label="操作" width="320px">
          <template #default="scope">
            <div class="c_table-operation align-content-center d-flex">
              <!--<el-link type="primary" size="small">网关配置</el-link>-->
              <!--<el-link type="primary" size="small" @click="showSaveFormDialog()">查看</el-link>-->
              <el-link
                title="网关在线时查看网关推送的数据" :disabled="!deviceStatusStore.gatewaysStatus[scope.row.id]" type="primary"
                size="small"
                @click="showDebuggerDialog(scope.row)"
              >
                调试
              </el-link>
              <!--:disabled="!deviceStatusStore.gatewaysStatus[scope.row.id]"-->

              <el-link type="primary" size="small" @click="showSaveFormDialog(scope.row)">编辑</el-link>
              <el-link type="primary" size="small" @click="showGatewayTransferDialog(scope.row)">网关转让</el-link>
              <el-link type="danger" size="small" @click="delTableItem(scope.row.id)">删除</el-link>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!--分页-->
      <el-affix target=".c_table-page" position="bottom" :offset="0">
        <yk-pagination class="c_table-pagination-page" :pages="pages" @handle="getTableData" />
      </el-affix>
    </div>
    <!--添加/修改表单-->
    <el-dialog
      v-model="saveFormDialogModel" :title="saveForm.id ? '编辑网关' : '添加网关'" width="860px"
      :close-on-click-modal="false" draggable :modal="false"
      @close="closeSaveFormDialog"
    >
      <el-form
        ref="saveFormRef" class="c_form-save mt-20" :model="saveForm"
        :rules="saveFormRules"
        label-width="110px"
      >
        <div class="d-grid" style="grid-template-columns: repeat(2, 1fr);">
          <el-form-item label="网关名称：" prop="name">
            <el-input v-model.trim="saveForm.name" placeholder="请输入网关名称" :maxlength="16" show-word-limit />
          </el-form-item>
          <el-form-item label="网关编号：" prop="number">
            <el-input v-model.trim="saveForm.number" placeholder="请输入网关编号" />
          </el-form-item>
          <el-form-item label="网关主题：" prop="topic" style="grid-column: span 2;">
            <el-input v-model.trim="saveForm.topic" placeholder="请输入网关主题" style="width: 430px;" type="textarea" />
          </el-form-item>
          <!--<el-form-item label="通讯密码：" prop="communicationPassword">-->
          <!--  <el-input v-model.trim="saveForm.communicationPassword" placeholder="请输入通讯密码" show-password />-->
          <!--</el-form-item>-->

          <el-form-item label="网关型号：" prop="model">
            <el-select v-model="saveForm.model" placeholder="请选择网关型号" disabled>
              <el-option value="">请选择</el-option>
              <el-option v-for="(item, index) in Array.from(gatewayModelMap)" :key="index" :label="item[1]" :value="item[0]" />
            </el-select>
          </el-form-item>
          <el-form-item label="物联网卡号：" prop="cardNumber">
            <el-input v-model.trim="saveForm.cardNumber" placeholder="请输入物联网卡号" />
          </el-form-item>
        </div>
        <el-form-item label="网关地址：">
          <div class="d-flex" @click="showCoordinatePickupDialog">
            <el-form-item prop="address">
              <el-input v-model.trim="saveForm.address" placeholder="请输入网关地址" style="width: 429px;" readonly />
            </el-form-item>
            <el-form-item prop="latitudeLongitude" class="ml-12">
              <el-input v-model.trim="saveForm.latitudeLongitude" placeholder="请输入网关经纬度" style="width: 229px;" readonly />
            </el-form-item>
          </div>
        </el-form-item>
        <el-form-item label="网关图片：">
          <div>
            <yk-upload-image v-model="gatewayImageFile" width="120px" height="120px">
              <el-image v-if="saveForm.model" :src="saveForm.model ? gatewayDefaultImageMap.get(saveForm.model)?.toString() : undefined" />
            </yk-upload-image>
            <p class="c_form-tip">图片建议尺寸140*140</p>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="c_form__submit-btn">
          <el-button type="primary" plain @click="closeSaveFormDialog">取消</el-button>
          <el-button type="primary" @click="submitSaveForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
    <!--坐标拾取-->
    <yk-coordinate-pickup v-model="coordinatePickupDialogModel" v-model:address.trim="saveForm.address" v-model:lnglat.trim="saveForm.latitudeLongitude" />
    <!--导入失败提醒-->
    <el-dialog
      v-model="importDialogModel" title="导入存在异常" width="550px"
      :close-on-click-modal="false" draggable :modal="false"
    >
      <div style="margin-top: -16px;">
        <p class="fs-16">导入时一些数据存在异常，以下是有存在问题的数据</p>
        <p class="color-danger-alpha-7 mt-1">*注：其余数据已导入，请勿重复导入</p>
      </div>
      <el-table :data="importErrorTableData" class="c_table-page mt-16" max-height="500px">
        <el-table-column prop="rowIndex" label="行号" width="100px" />
        <el-table-column prop="errorMsg" label="异常原因" />
      </el-table>
    </el-dialog>
    <!--调试-->
    <debugger-gateway
      :id="debuggerGatewayInfo?.id" v-model="debuggerDialogModel" is-dialog
      :name="debuggerGatewayInfo?.name"
      class="h-100"
    />
    <!--网关转让-->
    <el-dialog v-model="gatewayTransferDialogModel" title="网关转让" width="300px" @close="closeGatewayTransferDialog">
      <el-form ref="gatewayTransferFormRef" class="mt-20" :model="gatewayTransferForm" :rules="gatewayTransferFormRules">
        <el-form-item label="手机号" prop="phone">
          <el-input v-model="gatewayTransferForm.phone" placeholder="请输入分享人手机号" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button size="default" @click="closeGatewayTransferDialog">取消</el-button>
        <el-button type="primary" size="default" @click="gatewayTransferFormSubmit">确认</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
// 表格 - 设备列表
.table__device-list {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-gap: 16px;
}
</style>
